/**
* 各种实用函数
 * ver 3.6 做了tooltip,使用了mc的动态添加属性的功能，不是个很好的实现，但是现在来说暂时能用吧，凑合用先. ok
 * 
 * attach方法都做上一个applicationDomain
*/ 
package kgame5.kutil {
import kgame5.k3d.core.math.Vector3D;
import kgame5.k3d.core.obj3d.hardvo.HardVO;
import kgame5.kgu.spacial.SpacialManager;
import kgame5.kgui.kcomp.SmartList;
import kgame5.kgui.kcomp.SmartSliderBarV;
import kgame5.kmath.MathDG;

import mx.utils.StringUtil;

import flash.display.*;
import flash.events.*;
import flash.media.*;
import flash.net.*;
import flash.system.*;
import flash.utils.*;

public class Util{
	
//	//每次都有个这个，为了方便
//	public static const EVENTTYPE_CLICK_ITEM:String="EVENTTYPE_CLICK_ITEM";
//	
	//如果用editpust编辑的东西，则断行使用这个的
	public static const EDITPLUS_SPLIT:String=String.fromCharCode(13,10);
	
	//*********************hack技术强制垃圾收集************************
	public static function GC():void{
		T.p("::::::::::启动GC");
		try{
	        new LocalConnection().connect("kk");
	        new LocalConnection().connect("kk");
		}catch(error : Error){
			//trace("出错了啊",error);
		}
	}
	
	public static function VectorRemoveElement(v:Vector,aim:*):Boolean{
		var idx:int=v.indexOf(aim);
		if(idx!=-1){
			v.splice(idx, 1);
			return true;
		}
		return false;
	}
	
	public static function ConvertDict2Array(dict:Dictionary):Array{
		var a:Array=new Array();
		
		for each(var gameFSM:Object in dict){
			a.push(gameFSM);
		}
		return a;
	}
	//*********************检查是否一个动画到头了************************
	public static function isEndOfFrames(mc:MovieClip):Boolean{
		if(mc.currentFrame==mc.totalFrames){
			return true;
		}
		return false;
	}
	
	//*********************检查是否是有效的可被flash使用的图片地址************************
	public static function CheckPicUrl(sPicUrl:String):Boolean{
		//--
		var extendName : String = (sPicUrl.substr(-4, 4)).toUpperCase();
		//转换成大写
		//T.p("图片扩展名字:"+extendName);
		switch(extendName) {
			case ".PNG":
			case ".GIF":
			case ".JPG":
			case "JPEG":
			case ".SWF":
			return true;
		}
		return false;
	}
	


	//*********************取得文件加载的绝对地址，这个是为了加在嵌套flash用的
	public static function GetAbsUrl(stage:Stage):String{
		var absurl:String=stage.loaderInfo.url.substring(0,stage.loaderInfo.url.lastIndexOf("/")+1);
		T.p("GetAbsUrl:",absurl);
		return absurl;
	}
	
	//*********************RemoveMovieClip********************
	public static function Attach(linkedName:String,ad:ApplicationDomain=null):Object{
		var ClassReference:Class =null;
		if(ad==null){
			ClassReference=getDefinitionByName(linkedName) as Class;
		}else{
			ClassReference=ad.getDefinition(linkedName) as Class;
		}
		if(ClassReference==null){
			return null;
		}
         var instance:Object = new ClassReference();
         return instance;
	}
	
	public static function AttachBmd(linkedName:String,ad:ApplicationDomain=null):BitmapData{
		var ClassReference:Class =null;
		if(ad==null){
			ClassReference=getDefinitionByName(linkedName) as Class;
		}else{
			ClassReference=ad.getDefinition(linkedName) as Class;
		}
		if(ClassReference==null){
			return null;
		}
         var instance:Object = new ClassReference(0,0);
         return BitmapData(instance);
	}
	public static function AttachMC(linkedName:String,ad:ApplicationDomain=null):MovieClip{
		var ClassReference:Class =null;
		if(ad==null){
			ClassReference=getDefinitionByName(linkedName) as Class;
		}else{
			ClassReference=ad.getDefinition(linkedName) as Class;
		}
		if(ClassReference==null){
			return null;
		}
         var instance:Object = new ClassReference();
         return MovieClip(instance);
		
	}
	public static function AttachSD(linkedName:String,ad:ApplicationDomain=null):Sound{
		var ClassReference:Class =null;
		if(ad==null){
			ClassReference=getDefinitionByName(linkedName) as Class;
		}else{
			ClassReference=ad.getDefinition(linkedName) as Class;
		}
		if(ClassReference==null){
			return null;
		}
         var instance:Object = new ClassReference();
         return Sound(instance);
		
	}
	//加载一个动态的linkedMC当作bmd用，bmd是用来给3d用的
	public static function AttachMCAsBmd(linkID:String,transparent:Boolean=false,ad:ApplicationDomain=null):BitmapData{
		var mc:MovieClip=AttachMC(linkID,ad);
		//这个位图背景底色要是透明的，这样才能画出其他颜色
		var bmd:BitmapData=new BitmapData(mc.width,mc.height,transparent,0x00ff0000);
		bmd.draw(mc);
		return bmd;
		
	}
	//把一个东西从父里干掉
	public static function RemoveMovieClip(mc:DisplayObject){
		if(mc!=null&&mc.parent!=null){
			mc.parent.removeChild(mc);
		}
	}
	//*********************getURL********************
	public static function getURL(myUrl:String,windowMode:String="_blank"){
		if(myUrl==""||myUrl==null){
			return;
		}
		navigateToURL(new URLRequest(myUrl),windowMode);
	}
	
	//*********************ToolTip********************
	public static function CreateToolTip(mc:MovieClip,s:String,x:Number,y:Number){
		var mc_ktooltip:MovieClip=AttachMC("MyMc_ToolTip");
		mc.addChild(mc_ktooltip);
		
		mc_ktooltip.x=x;
		mc_ktooltip.y=y;
		//mc_ktooltip.name="mc_ktooltip";
		mc_ktooltip.visible=false;
		
		mc.mc_ktooltip=mc_ktooltip;//真是不好的实现啊
		
		SetToolTipText(mc,s);
		
		//注册事件
		//
		mc.handler_ktooltip_mover=function(e:MouseEvent){
			//trace("over88");
			var mc_target:MovieClip=e.currentTarget as MovieClip;
			//trace(mc_target,e.currentTarget);
			var mc_tip:DisplayObject=mc_target.mc_ktooltip;
			//trace(mc_tip);
			mc_tip.visible=true;
			
		};
		mc.handler_ktooltip_mout=function(e:MouseEvent){
			//trace("out88");
			var mc_target:MovieClip=e.currentTarget as MovieClip;
			
			var mc_tip:DisplayObject=mc_target.mc_ktooltip;
			mc_tip.visible=false;
		};
		mc.addEventListener(MouseEvent.MOUSE_OVER,mc.handler_ktooltip_mover,false,0,true);
		mc.addEventListener(MouseEvent.MOUSE_OUT,mc.handler_ktooltip_mout,false,0,true);
	}
	public static function SetToolTipText(mc:MovieClip,s:String){
		
		var mc_ktooltip:MovieClip=mc.mc_ktooltip ;
		
		if(mc_ktooltip.tf!=null){
			mc_ktooltip.tf.text=s;
		}
	}
	public static function ClearToolTip(mc:MovieClip){
		mc.removeEventListener(MouseEvent.MOUSE_OVER,mc.handler_ktooltip_mover);
		mc.removeEventListener(MouseEvent.MOUSE_OUT,mc.handler_ktooltip_mout);
		RemoveMovieClip(mc.mc_ktooltip);
	}
	
	//*********************slidermenu********************
	//一个可以滑动的菜单，鼠标进入他的响应区域才
	//结构为mc_mask和mc_btnpad
//	public static function CreateSliderMenu(mc:MovieClip,Dur:Number){
//		
//		mc.mc_EA.alpha=0;//这个事件区域是必须要有的,否则检测不到啊
//		
//		mc.handler_slidermenu_mover=function(e:MouseEvent){
//			//trace("over",e.target.name,e.currentTarget.name)
//			Tween2DX.StartMoveY(mc.mc_btnpad,-mc.mc_btnpad.height,Dur);
//		};
//		mc.handler_slidermenu_mout=function(e:MouseEvent){
//			//trace("out",e.target.name,e.currentTarget.name)
//			Tween2DX.StartMoveY(mc.mc_btnpad,1,Dur);
//		};
//		mc.addEventListener(MouseEvent.MOUSE_OVER,mc.handler_slidermenu_mover,false,0,true);
//		mc.addEventListener(MouseEvent.MOUSE_OUT,mc.handler_slidermenu_mout,false,0,true);
//	}
	
	//交换2维数组中两个元素，注意，这个两2维数组也能交换\
	public static function SwapArray2Elem(a:Array,j:Number,k:Number):void{
		var a_temp:Number=a[j];
		a[j]=a[k];
		a[k]=a_temp;
	}
	
	
	//两个mc(或者是button或者)原点相等,就是mc._x=mark._x
	public static function AlignXY(mc:DisplayObject,mark:DisplayObject){
		mc.x=mark.x;
		mc.y=mark.y;
	}
	//
	public static function AlignWH(mc:DisplayObject,mark:DisplayObject){
		mc.width=mark.width;
		mc.height=mark.height;
	}
	
	public static function AlignXYWH(mc:DisplayObject,mc_mark:DisplayObject){
		AlignXY(mc,mc_mark);
		AlignWH(mc,mc_mark);
		mc_mark.visible=false;
	}
	/*
	public static function GetAbsUrl():String{
		var absurl=_root._url.substring(0,_root._url.lastIndexOf("/")+1);
		return absurl;
	}
	//*/
	
	/*
	//***************************************************************************
	//这个暂时还不能使用，因为他会和EffectManager里的函数冲突，但是最好这两个函数应该放到这里
	//**************************************************************************
	//向一个mc里面添加另一个mc
	static var DEPTH:Number=1000;
	public static function AddMovieClip(mc_container:MovieClip,linkID:String):MovieClip{
		var depth:Number=DEPTH++;//mc_container.getNextHighestDepth();
		if(depth==9876){//因为9876是Tween使用的图层，禁止使用
			depth++;
		}
		var mc:MovieClip=mc_container.attachMovie(linkID,linkID+"_linked_"+depth,depth);
		
		//T.p("AddMovieClip:"+mc_container+" !! "+mc);
		return mc;
	}
	public static function CreateEmptyMovieClip(mc_container:MovieClip):MovieClip{
		var depth:Number=DEPTH++;//mc_container.getNextHighestDepth();
		if(depth==9876){//因为9876是Tween使用的图层，禁止使用
			depth++;
		}
		var mc:MovieClip=mc_container.createEmptyMovieClip("mc_empty_"+depth,depth);
		
		//T.p("CreateMovieClip:"+mc_container+" !! "+mc);
		return mc;
	}
	//*/
	//将button和menu绑定,注意btn可能是movieClip也可能是button
	//效果是当点按钮时弹出或关闭菜单，当点菜单外部时菜单关闭
//	public static function BindBtnAndMenu(btn:InteractiveObject,menu:MovieClip){
//		//T.p("BindBtnAndMenu",btn,menu);
//		//
//		menu.visible = false;
//		
//		//打开
//		Util.OnPress(btn, 
//					function (e:MouseEvent){
//						if(menu.visible == false){//如果没有显示菜单则
//							Tween2DX.StartFade(menu,1,0.3);
//						}else{//已经显示了则关闭
//							Tween2DX.StartFade(menu,0,0.2);
//						}
//						//这个很重要的，否则鼠标按下的事件传到stage,就要执行OnStageMouseDown
//						e.stopImmediatePropagation();
//					}
//		);
//		
//		//
//		Util.OnStageMouseDown(menu, 
//							function(e:MouseEvent){
//								if (menu.visible&&menu.hitTestPoint (e.stageX,e.stageY) == false){
//									Tween2DX.StartFade(menu,0,0.2);
//								}
//							}
//		);
//	}
	//把MC做成按钮,这个也就是歌词模块用,注意tabCjhider和mouseCHildren的默认值
	//这个mc需要有_up,_down,_over的标签
	public static function MakeMCButton(mc:MovieClip){
		mc.mouseChildren=false;
		mc.buttonMode=true;//
		mc.gotoAndStop(1);
	}
	
	//构造一个2维数组并且将他初始化为0
	public static function  NewArray2_Int (row:int, col:int):Array {
		var a:Array = new Array (row);
		for (var i:int = 0; i < a.length; i++) {
			var b:Array = new Array (col);
			for (var j:int = 0; j < b.length; j++) {
				b[j] = 0;
			}
			a[i] = b;
		}
		return a;
	}
	
	//构造一个2维数组并且将他初始化为0
	public static function  NewArray2_Number (row:int, col:int,value:Number=0):Array {
		var a:Array = new Array (row);
		for (var i:int = 0; i < a.length; i++) {
			var b:Array = new Array (col);
			for (var j:int = 0; j < b.length; j++) {
				b[j] = value;
			}
			a[i] = b;
		}
		return a;
	}
	
	//构造一个2维数组并且将他初始化为Object
	public static function NewArray2_Obj (row:int, col:int):Array {
		var a:Array = new Array (row);
		for (var i:int = 0; i < a.length; i++) {
			var b:Array = new Array (col);
			
			a[i] = b;
		}
		return a;
	}
	//复制一个2维数组
	public static function CopyArray2(src:Array):Array{
		var aim:Array=new Array();
		
		var RC:int=src.length;
		var CC:int=src[0].length;
		for(var r:int=0;r<RC;r++){
			aim.push(new Array());
			for(var c:int=0;c<CC;c++){
				aim[r][c]=src[r][c];
			}
		}
		return aim;
	}
	
	//获得16进制编码的一个字符串
		public static function getHexContext(s : String) : String {
			var b : ByteArray = new ByteArray();
			for(var i : int = 0;i < s.length;i += 2) {
				var v : int = parseInt("0x"+s.charAt(i)) << 4 | parseInt("0x"+s.charAt(i + 1));
				b.writeByte(v);
			}	
			b.position=0;
			b.uncompress();			
			return b.readUTFBytes(b.length);				
		}
	/////////////////////////
	public static function AEvent(txt : String,link : String) : String {
		return "<a href='event:" + link + "'>" + txt + "</a>";
	}
	//注意颜色前面要是#
	public static function CreateColorHtml(text:String,color:String="#ff0000"):String{
		return "<font color='"+color+"'>"+text+"</font>";
	}	

	public static function ImgTag(link : String) : String {
		return "<img src='" + link + "'></img>" ;
	}		
	public static function getByteArray(str : String) : ByteArray {
		var	 ba : ByteArray = new ByteArray();
		ba.writeUTFBytes(str);
		return ba;
	}	
	
	//深度复制
	public static function DeepClone(source : Object) : * {
		var myBA : ByteArray = new ByteArray();
		myBA.writeObject(source);
		myBA.position = 0;
		return myBA.readObject();
	}
	
	//创建一个下列表框，
	public static function CreateSmartList(width:int,height:int,itemHeight:int,sSliderBarLinkName:String):SmartList{
		var sb:SmartSliderBarV=new SmartSliderBarV(Util.AttachMC(sSliderBarLinkName), height);
		var smartList:SmartList=new SmartList(width,height, sb, itemHeight);
		smartList.clear();
		return smartList;
	}
	
	//布置一个表格,按指定的行间距，列间距和总列数布置
	public static function placeAtTable(idx:int,spaceH:int,spaceV:int,CC:int):Object{
		var row:int=idx/CC+1;
		var col:int=idx%CC;
		var x:int=spaceV*row;
		var y:int=spaceH*col;
		return {x:x,y:y};
	}
	
	//做一个鼠标屏蔽,不能透过这个东西点下面的东西
	public static function MakeMB(mc_mb:MovieClip){
		mc_mb.buttonMode=true;
		mc_mb.useHandCursor=false;
		mc_mb.visible=false;
	}
	
	//从excel的xml里提取数据
//	private  function readData(xml : XML) {
//		var ns : Namespace = xml.namespace();
//		var rows = xml..ns::Row;
//		for each (var r in rows) {
//			var cellData = r.ns::Cell.ns::Data.text();
//			//var str : String = "";
//			var aCol : Array = new Array();
//			for each (var d in cellData) {
//				//str += d + ",";
//				aCol.push(d);
//			}
//			distillTI(aCol);
//			distillTBI(aCol);
//			//trace("一行数据");
//			//trace(str);
//		}
//	}

	//生成URL字符串，这个是说服务器是认为utf-8解码的
		public static function MakeURLParam( ...param) : String {
			var sb : String = "";
    
			var isfirst : Boolean = true;
			try {
				if (param != null && param.length > 1) {
					sb += "?";
					for (var i : int = 0;i < param.length; i += 2) {
						if (param[i + 1] != null) {
							if (!isfirst) {
								sb += "&";              
							}
							sb += param[i];
							sb += "=";
            
							var value : String = param[i + 1] != null ? param[i + 1].toString() : "null";
							value = encodeURIComponent(value);
							sb += value;
							isfirst = false;
						}
					}
				}
			}
    		catch (ex : Error) {
    			throw new Error("编码失败!");
			}
			return sb;
		}
		//这个是在一个字符串解析的时候用的
	public static function StringToIntArray(s:String):Array{
		var a:Array=s.split(",");
		var aa:Array=new Array();
		for(var i:int=0;i<a.length;i++){
			aa[i]=parseInt(a[i]);
		}
		return aa;
	}
	
	//解析外部一个text文本的数据
//A:50
//B:50
//H:27
//R:32
//chestY:26
//waistY:8
//wheel1X:18
//wheel1Y:8
//wheel1Z:15
//wheel2X:18
//wheel2Y:8
//wheel2Z:0
//wheel3X:18
//wheel3Y:8
//wheel3Z:-15
	public static function ParseTxtPair(txt:String):Dictionary{
		//T.p("--ParseTxtPair--");
		//T.p(txt);
		var dict:Dictionary=new Dictionary();
		var a:Array=txt.split("\n");
		for each(var k:String in a){
			//T.p(k);
			var b:Array=k.split(":");
			dict[b[0]]=parseInt(b[1]);
			//T.p("key:"+b[0]);
			//T.p("value:"+b[1]);
		}
		return dict;
	}
	
	//这个是读取一个txt,快速的把它分段并解析出来
	public static function ReadTxt(s:String):Array{
		
		//T.p(ll.data);
		var reg:RegExp=/\r/g;
		s=s.replace(reg,"");
		var aa:Array=s.split("#");
		aa[0]=StringUtil.trim(aa[0]);
		var iii:Array=aa[0].split("\n");
		
		return iii;
		
	
	}
		//是否在坦克雷达照射范围内.这个只处理坦克四方向
	public static function IsInRadarRange(me:HardVO,em:HardVO,radarMinRadius:int,radarMaxRadius:int,radarAngleRange:int):Boolean{
		//T.p("IsInRadarRange", me.v3d_p, em.v3d_p, me.v3d_r.y);
		//判断距离是否合格
		var dist:int=Vector3D.SGetDistance(me.v3d_p, em.v3d_p);
		if(dist>radarMaxRadius||dist<radarMinRadius){//不在圆环内的不射击
			return false;
		}
		
		//判断角度是否合格
		var dd:Vector3D=new Vector3D(0,0,0);
		Vector3D.SSub(em.v3d_p, me.v3d_p, dd);
		var angleDD:int=dd.angleOfXOZ();//计算敌人到我的角度
		//T.p("连线",angleDD);
		angleDD=MathDG.C360(angleDD);
		//var tankRotY:int=MathDG.C360(me.v3d_r.y);
		var tt:int=angleDD-me.v3d_r.y;
		//tt=MathDG.C360(tt);
		//T.p("角度",tt);
		//0度特殊处理
		if(me.v3d_r.y==0){
			if(tt>180){
				tt-=360;
			}
		}
		
		//-
		if(Math.abs(tt)<=radarAngleRange/2){
			return true;
		}else{
			return false;
		}
	}
	
	//根据一个导弹的v3d_p和v3d_v来计算它的落点
	//计算一个东西的落点
	public static function CalcDropPoint(p:Vector3D,v:Vector3D):Vector3D{
		//T.p("CalcDropPoint");
		//T.p(p,v);
		
		var G:int= -SpacialManager.G;
		
		var result:Vector3D=new Vector3D();
		var t:int=0;//总时间
		//计算时间
		//t1 上升时间
		var t1:Number=v.y/G;
		//t2 下落时间
		var s:Number=p.y+G*t1*t1*0.5;
		var t2:Number=Math.sqrt(2*s/G);
		//总时间
		t=t1+t2+1;//1是为了弥补一下误差
		
		//飞行时间乘以速度即可
		result.x=v.x*t;
		result.z=v.z*t;
		//T.p(t1,t2,s);
		result.add(p);
		result.y=0;
		//T.p("result",result);
		return result;
	}
	////*********************OnPress********************
	//把鼠标按下绑定到一个行为上,这个的mc是InteractiveObject,可以是Mc也可以是btn
	public static function OnPress(mc:InteractiveObject,func_exe:Function,bUseHandCursor:Boolean=true){
		//T.p("OnPress",mc);
		if(mc is Sprite){//如果是Sprite要可以显示手
			Sprite(mc).buttonMode=bUseHandCursor;
		}
		//T.p(mc+" 注册OnPress");
		//最后一个参数很重要，弱引用
		mc.addEventListener(MouseEvent.MOUSE_DOWN,func_exe,false,0,true);
	}
	//把鼠标按下绑定到一个行为上,这个的mc是InteractiveObject,可以是Mc也可以是btn
	public static function OnClick(mc:InteractiveObject,func_exe:Function,bUseHandCursor:Boolean=true){
		//T.p("OnPress",mc);
		if(mc is Sprite){//如果是Sprite要可以显示手
			Sprite(mc).buttonMode=bUseHandCursor;
		}
		//T.p(mc+" 注册OnPress");
		//最后一个参数很重要，弱引用
		mc.addEventListener(MouseEvent.CLICK,func_exe,false,0,true);
	}
	//按键
	public static function OnKeyDown(mc:InteractiveObject,func_exe:Function){
		//T.p(mc+" 注册OnPress");
		//最后一个参数很重要，弱引用
		mc.addEventListener(KeyboardEvent.KEY_DOWN,func_exe,false,0,true);
	}
	public static function OnStageMouseDown(mc:InteractiveObject,func_exe:Function){
		mc.stage.addEventListener(MouseEvent.MOUSE_DOWN,func_exe,false,0,true);
	}
	
	public static function SafelyRemoveChild(p:DisplayObjectContainer,c:DisplayObject):Boolean{
		if(c!=null && p.contains(c)){
			p.removeChild(c);
			return true;
		}
		return false;
	}
}//end of class
}

/////////////////////////////////////////////////////
